package edu.cmu.ibill.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.mybeans.dao.DAOException;
import org.mybeans.factory.Transaction;

import edu.cmu.ibill.databeans.Debt;
import edu.cmu.ibill.databeans.PersonalBill;
import edu.cmu.ibill.databeans.User;
import edu.cmu.ibill.model.CategoryDictDAO;
import edu.cmu.ibill.model.DebtDAO;
import edu.cmu.ibill.model.Model;
import edu.cmu.ibill.model.PersonalBillDAO;
import edu.cmu.ibill.model.UserDAO;
import edu.cmu.ibill.util.StringProcessor;

public class AddPaymentAction extends Action {

	UserDAO userDAO;
	PersonalBillDAO personalDAO;
	DebtDAO debtDAO;
	CategoryDictDAO categorydictDAO;

	SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");

	String amount;
	String date;
	String comment;
	String category;

	public AddPaymentAction(Model model) {
		this.debtDAO = model.getDebtDAO();
		this.personalDAO = model.getPersonalBillDAO();
		this.userDAO = model.getUserDAO();
		this.categorydictDAO = model.getCategoryDictDAO();
	}

	@Override
	public String getName() {
		return "addpayment.do";
	}

	@Override
	public String perform(HttpServletRequest request) {
		List<String> errors = new ArrayList<String>();
		request.setAttribute("addpayedmenterrors", errors);
		request.setAttribute("categorydict", categorydictDAO.getAllCategoryNames());
		User user = (User) request.getSession(false).getAttribute("user");

		if (user == null || user.getId() == -1) {
			request.getSession(false).setAttribute("user", null);

			// TODO return login?
			return "login.jsp";
		}

		// Get corresponding information from the request.
		amount = request.getParameter("amount");
		amount = StringProcessor.process(amount);		
		date = request.getParameter("date");
		comment = request.getParameter("comment");
		comment = StringProcessor.process(comment);
		category = "16";
		
		request.setAttribute("amount", amount);
		request.setAttribute("comment", comment);
		request.setAttribute("date", date);
		
		String owedUserEmail = request.getParameter("email");
		User oUser = userDAO.Lookup(owedUserEmail);
		
		request.setAttribute("email", owedUserEmail);
		
		if(oUser == null)
			errors.add("Email address doesn't exist!");

		// Validate the errors.
		errors.addAll(this.getValidationErrors());

		if (errors.size() != 0) {
			PersonalBill[] pBills = personalDAO.LookupByUserId(user.getId());
			request.setAttribute("personalbills", pBills);
			request.setAttribute("addpayementinprocess", "");
			return "manage.jsp";
		}

		// Commit the personalBill and all the debt records to the database.
		try {

			/**
			 * Create and store the personal bill record to database. This bill
			 * records the personal who pay the money
			 */
			PersonalBill payedBill = new PersonalBill();
			payedBill.setAmount(Double.parseDouble(amount));
			payedBill.setDate(new java.sql.Date(format.parse(date).getTime()));
			payedBill.setCategoryId(Integer.parseInt(category));
			payedBill.setDescription(comment);
			// It is a shared bill.
			payedBill.setIsShared(true);
			payedBill.setUserId(user.getId());

			//Get bill id.
			payedBill.setId(personalDAO.create(payedBill));

			
			/**
			 * Create and store the personal bill record to database. This bill
			 * records the personal who receive the money
			 */
			PersonalBill owedBill = new PersonalBill();
			owedBill.setAmount(-Double.parseDouble(amount));
			owedBill.setDate(new java.sql.Date(format.parse(date).getTime()));
			owedBill.setCategoryId(Integer.parseInt(category));
			owedBill.setDescription(comment);
			// It is a shared bill.
			owedBill.setIsShared(true);
			owedBill.setUserId(oUser.getId());

			//Get bill id.
			owedBill.setId(personalDAO.create(owedBill));

			Debt debt = new Debt();
			debt.setAmount(payedBill.getAmount());
			debt.setDate(payedBill.getDate());
			debt.setDescription(payedBill.getDescription());
			debt.setOwedBillId(owedBill.getId());
			debt.setPayedBillId(payedBill.getId());
			// Set the id of the user who received the money
			debt.setOwedId(owedBill.getUserId());
			// Set the id of the user who paid the money
			debt.setPayedId(payedBill.getUserId());

			debtDAO.create(debt);

			PersonalBill[] pBills = personalDAO.LookupByUserId(user.getId());
			request.setAttribute("personalbills", pBills);
			return "manage.jsp";
		} catch (ParseException e) {

			errors.add(e.getMessage());
			PersonalBill[] pBills = personalDAO.LookupByUserId(user.getId());
			request.setAttribute("personalbills", pBills);
			request.setAttribute("addpayementinprocess", "");
			return "manage.jsp";
		} catch (DAOException e) {
			
			errors.add(e.getMessage());
			PersonalBill[] pBills = personalDAO.LookupByUserId(user.getId());
			request.setAttribute("personalbills", pBills);
			request.setAttribute("addpayementinprocess", "");
			return "manage.jsp";
		} finally {
			if (Transaction.isActive())
				Transaction.rollback();
		}
	}

	public List<String> getValidationErrors() {

		List<String> errors = new ArrayList<String>();

		if (date == null || date.length() == 0) {
			errors.add("date is empty");
		} else {
			SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");

			try {
				java.util.Date d = format.parse(date);
				Calendar currentDate = Calendar.getInstance();
				if (currentDate.getTime().before(d)) {
					errors.add("invalid date for a future time");
				}
			} catch (ParseException e) {
				errors.add("invalid format for date");
			}

		}

		if (category == null || category.length() == 0) {
			errors.add("category is empty");
		} else {
			if (Integer.parseInt(category) == 0) {
				errors.add("category is empty");
			}
		}

		if (amount == null || amount.length() == 0) {
			errors.add("amount is empty");
		} else {
			try {
				Double.parseDouble(amount);
			} catch (NumberFormatException e) {
				errors.add("invalid format for amount");
			}
		}

		return errors;
	}

}
